home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / ada / adaed-1.11 / adaed-1 / Adaed-1.11.0a / predef6.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-07  |  9.9 KB  |  398 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9. /*    +---------------------------------------------------+
  10.       |                                                   |
  11.       |          I N T E R P     P R E D E F S            |
  12.       |            Part 6: Editing Procedures             |
  13.       |                  (C Version)                      |
  14.       |                                                   |
  15.       |   Adapted From Low Level SETL version written by  |
  16.       |                                                   |
  17.       |                  Monte Zweben                     |
  18.       |               Philippe Kruchten                   |
  19.       |               Jean-Pierre Rosen                   |
  20.       |                                                   |
  21.       |    Original High Level SETL version written by    |
  22.       |                                                   |
  23.       |                   Clint Goss                      |
  24.       |               Tracey M. Siesser                   |
  25.       |               Bernard D. Banner                   |
  26.       |               Stephen C. Bryant                   |
  27.       |                  Gerry Fisher                     |
  28.       |                                                   |
  29.       |              C version written by                 |
  30.       |                                                   |
  31.       |               Robert B. K. Dewar                  |
  32.       |                                                   |
  33.       +---------------------------------------------------+
  34. */
  35.  
  36. /* This module contains routines for the implementation of some of
  37.  * the predefined Ada packages and routines, namely SEQUENTIAL_IO,
  38.  * DIRECT_IO, TEXT_IO, and CALENDAR. Part 6 contains the routines
  39.  * for generating string images of internal objects.
  40. */
  41.  
  42. #include "ipredef.h"
  43.  
  44. static double image_real_digits (double, int, char *);
  45. static void image_real (double, int, int, int);
  46.  
  47. /* IMAGE_REAL_DIGITS */
  48.  
  49. /* Procedure to output number of digits specified by multiplying dval, which
  50.  * is non-negative and less than 1.0, successively by 10. Output digits are
  51.  * placed in string s. The value returned is the reduced value of dval. For
  52.  * example, if dval is 0.314689 on entry, and n is 3, then the characters 314
  53.  * are output, and the returned value is 0.689
  54. */
  55.  
  56. static double image_real_digits (double dval, int n, char *s)
  57.                                                         /*;image_real_digits*/
  58. {
  59.     int     i;
  60.  
  61.     while (n--) {
  62.         dval *= 10.0;
  63.         i = (int)dval;
  64.         *s++ = '0' + i;
  65.         dval = dval - (double)i;
  66.     }
  67.     return dval;
  68. }
  69.  
  70.  
  71. /* IMAGE_REAL */
  72.  
  73. /* This routine is shared for fixed and float values. It returns a string image
  74.  * of the double value dval, using fore, aft, exp as described in 14.3.8. The
  75.  * resulting string image is stored in work_string. Note: if fore is zero, then
  76.  * the string has the minimum required number of characters before the point.
  77.  * If an out of range value is encountered, the exception in data_exception
  78.  * is raised. If a bad character is encountered, DATA_ERROR is raised.
  79. */
  80.  
  81. static void image_real (double dval, int fore, int aft, int exp) /*;image_real*/
  82. {
  83.     int     exponent;
  84.     char    sign;
  85.     char    *s, *t;
  86.     int     total_digits;
  87.     int     exp_digits;
  88.     double  round;
  89.  
  90.     /* Set pointer s to generate output characters in work string */
  91.  
  92.     s = work_string;
  93.  
  94.     /* Make sure fore, aft, exp have acceptable values. 14.3.7 does not
  95.      * justify limiting fore, aft and exp to 512, but it seems reasonable!
  96.     */
  97.  
  98.     if (fore <= 0) fore = 1;
  99.     else if (fore > 512) fore = 512;
  100.  
  101.     if (aft < 0) aft = 0;
  102.     else if (aft > 512) aft = 512;
  103.  
  104.     if (exp < 0) exp = 0;
  105.     else if (exp > 512) exp = 512;
  106.  
  107.     /* Deal with 0.0 specially */
  108.  
  109.     if (dval == 0.0) {
  110.         while (fore-- > 1) *s++ = ' ';
  111.         *s++ = '0';
  112.         *s++ = '.';
  113.  
  114.         while (aft--) *s++ = '0';
  115.  
  116.         if (exp) {
  117.             *s++ = 'E';
  118.             *s++ = '+';
  119.             exp--;
  120.             exp = MAX(exp,1);
  121.  
  122.             while (exp--) *s++ = '0';
  123.         }
  124.         *s = 0;
  125.         return;
  126.     }
  127.  
  128.     /* If non-zero capture sign */
  129.  
  130.     if (dval < 0.0) {
  131.         sign = '-';
  132.         dval = -dval;
  133.         fore--;
  134.     }
  135.     else sign = '+';
  136.  
  137.     /* Reduce number to range 0.1 <= dval < 1.0, except that we do not
  138.      * scale up if there is no exponent field, since we are happy with
  139.      * leading zeroes in this case
  140.     */
  141.  
  142.     exponent = 0;
  143.     if (exp != 0) {
  144.         while (dval < 0.1) {
  145.             exponent--;
  146.             dval *= 10.0;
  147.         }
  148.     }
  149.  
  150.     while (dval >= 1.0) {
  151.         exponent++;
  152.         dval /= 10.0;
  153.     }
  154.  
  155.     /* A special case, if there is no exponent field, we want at least one
  156.      * digit in front of the point, which means that the exponent value
  157.      * should be at least one to get the proper value for this digit.
  158.     */
  159.  
  160.     if (exp == 0 && exponent == 0) {
  161.         exponent++;
  162.         dval /= 10.0;
  163.     }
  164.  
  165.     /* To round up, we must add a 5 in the place one past the last one to
  166.      * be displayed. For the case of no exponent field there are exponent
  167.      * digits before the point, otherwise there is only one digit. Note
  168.      * that it is possible for rounding to push us back over 1.0
  169.     */
  170.  
  171.     if (exp == 0) total_digits = aft + exponent;
  172.     else total_digits = aft + 1;
  173.  
  174.     round = 0.5;
  175.     while (total_digits--) round /= 10.0;
  176.  
  177.     dval += round;
  178.  
  179.     if (dval >= 1.0) {
  180.         dval /= 10.0;
  181.         exponent++;
  182.     }
  183.  
  184.     /* Convert number for case of no exponent field present */
  185.  
  186.     if (exp == 0) {
  187.         while (fore > exponent) {
  188.             fore--;
  189.             *s++ = ' ';
  190.         }
  191.  
  192.         if (sign == '-') *s++ = sign;
  193.  
  194.         dval = image_real_digits(dval,exponent,s);
  195.         s += exponent;
  196.         *s++ = '.';
  197.         image_real_digits(dval,aft,s);
  198.         s += aft;
  199.     }
  200.  
  201.     /* Convert number for case of exponent present */
  202.  
  203.     else {
  204.         while (fore > 1) {
  205.             fore--;
  206.             *s++ = ' ';
  207.         }
  208.  
  209.         if (sign == '-') *s++ = sign;
  210.  
  211.         dval = image_real_digits(dval,1,s);
  212.         s++;
  213.         *s++ = '.';
  214.         image_real_digits(dval,aft,s);
  215.         s += aft;
  216.  
  217.         /* Convert the exponent, first output E and sign */
  218.  
  219.         exponent--;          /* since one digit before point */
  220.         *s++ = 'E';
  221.         if (exponent < 0) {
  222.             exponent = -exponent;
  223.             *s++ = '-';
  224.         }
  225.         else *s++ = '+';
  226.         exp--;               /* to account for sign */
  227.         if (exp == 0) exp=1; /* but leave at least one digit */
  228.  
  229.         /* Output digits of exponent */
  230.  
  231.         t = s + 64;          /* cannot be more than 64 non-zero dec digits! */
  232.         exp_digits = 0;
  233.         while (exponent) {
  234.             exp_digits++;
  235.             *--t = '0' + (exponent % 10);
  236.             exponent /= 10;
  237.         }
  238.  
  239.         while (exp-- > exp_digits) *s++ = '0';
  240.         while (exp_digits--) *s++ = *t++;
  241.     }
  242.  
  243.     /* Conversion is complete */
  244.  
  245.     *s = 0;
  246. }
  247.  
  248.  
  249. /* IMAGE_INTEGER */
  250.  
  251. /* Returns a string image of item using the given base in work_string. If
  252.  * an out of range value is encountered, the exception in data_exception
  253.  * is raised. If a bad character is encountered, DATA_ERROR is raised.
  254. */
  255.  
  256. void image_integer(int item, int base)               /*;image_integer*/
  257. {
  258.     char    *p, *q;
  259.     int     digit;
  260.  
  261.     /* Convert base if not 10 */
  262.  
  263.     p = work_string;
  264.     if (base != 10) {
  265.         if (base > 10) {
  266.             *p++ = '1';
  267.             *p++ = '0' + base - 10;
  268.         }
  269.         else *p++ = base + '0';
  270.         *p++ = '#';
  271.     }
  272.  
  273.     /* Deal with sign. Note: we work with the negative of the absolute
  274.      * value of the number so that we do not have to make special checks
  275.      * for the largest negative number in the twos complement case.
  276.     */
  277.  
  278.     if (item < 0) *p++ = '-';
  279.     else item = -item;
  280.  
  281.     /* Convert value to digit string in specified base */
  282.  
  283.     if (item == 0) {
  284.         *p++ = '0';
  285.     }
  286.     else {
  287.         q = work_string + 15;
  288.         *q = 0;
  289.         while(item) {
  290.             digit = -(item % base);
  291.             item /= base;
  292.             *--q = (digit > 9) ? digit - 10 + 'A' : digit + '0';
  293.         }
  294.         while(*p++ = *q++);
  295.         p--;
  296.     }
  297.  
  298.     /* Add final # if based, and we are done */
  299.  
  300.     if (base != 10) *p++ = '#';
  301.     *p = 0;
  302. }
  303.  
  304.  
  305. /* IMAGE_FIXED */
  306.  
  307. /* Returns a string image of the fixed point value item_val, where item_type
  308.  * is a pointer to the type template, and fore, aft and exp control the
  309.  * format according to the rules in 14.3.8. The result is in work_string.
  310.  * Note: if fore is zero, then the result string has the minimum required
  311.  * number of characters before the point. If an out of range value is
  312.  * encountered, the exception in data_exception is raised. If a bad character
  313.  * is encountered, DATA_ERROR is raised.
  314. */
  315.  
  316. void image_fixed (long item_val, int *item_type, int fore, int aft, int exp)
  317.                                                             /*;image_fixed*/
  318. {
  319.     int     exp2, exp5;
  320.     double  dval;
  321.  
  322.     exp2 = FX_RANGE(item_type)->small_exp_2;
  323.     exp5 = FX_RANGE(item_type)->small_exp_5;
  324.  
  325.     dval = (double)item_val;
  326.  
  327.     while (exp2 > 0) {
  328.         exp2--; 
  329.         dval *= 2.0;
  330.     }
  331.     while (exp2 < 0) {
  332.         exp2++; 
  333.         dval /= 2.0;
  334.     }
  335.     while (exp5 > 0) {
  336.         exp5--; 
  337.         dval *= 5.0;
  338.     }
  339.     while (exp5 < 0) {
  340.         exp5++; 
  341.         dval /= 5.0;
  342.     }
  343.  
  344.     image_real (dval,fore,aft,exp);
  345. }
  346.  
  347.  
  348. /* IMAGE_FLOAT */
  349.  
  350. /* Returns a string image of the float value item_val, where fore, aft and
  351.  * exp control the format according to the rules in 143.8. The result is in
  352.  * work_string. Note: if fore is zero, then the result string has the minimum
  353.  * required number of characters before the point. If an out of range value is
  354.  * encountered, the exception in data_exception is raised. If a bad character
  355.  * is encountered, DATA_ERROR is raised.
  356. */
  357.  
  358. void image_float (float num, int fore, int aft, int exp)        /*;image_float*/
  359. {
  360.     image_real ((double)(num),fore,aft,exp);
  361. }
  362.  
  363.  
  364. /* IMAGE_ENUM */
  365.  
  366. /* Procedure to return the value of the given enumeration type value as a
  367.  * string in work_string. The type_ptr parameter points to the type or
  368.  * subtype template to be used for the operation.
  369.  */
  370.  
  371. void image_enum(int enum_val, int *type_ptr)                  /*;image_enum*/
  372. {
  373.     int     *ptr;
  374.     char    *c;
  375.     int     lit_len;
  376.  
  377.     if (TYPE(type_ptr) == TT_E_RANGE)    /* an actual subtype */
  378.         type_ptr = ADDR(E_RANGE(type_ptr) -> ebase, E_RANGE(type_ptr) -> eoff);
  379.  
  380.     enum_val -= E_RANGE(type_ptr) -> elow;
  381.     ptr = type_ptr + WORDS_E_RANGE;/* names are just past template */
  382.     lit_len = *ptr++;
  383.     c = work_string;
  384.     if (lit_len == -1) { /* special case for character */
  385.         *c++ = QUOTE;
  386.         *c++ = enum_val;
  387.         *c++ = QUOTE;
  388.     }
  389.     else {
  390.         while(enum_val--) {
  391.             ptr += lit_len;
  392.             lit_len = *ptr++;
  393.         }
  394.         while(lit_len--) *c++ = *ptr++;
  395.     }
  396.     *c = 0;
  397. }
  398.